package br.univali.compiladores.compilador.gui;

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.regex.Pattern;

import javax.swing.Action;
import javax.swing.JOptionPane;

import com.sun.org.apache.xml.internal.security.encryption.XMLEncryptionException;

import br.univali.compiladores.compilador.semantico.CodigoInstrucao;
import br.univali.compiladores.compilador.semantico.InstrucaoMaquinaVirtual;
import br.univali.compiladores.maquinavirtual.Finish;
import br.univali.compiladores.maquinavirtual.In;
import br.univali.compiladores.maquinavirtual.MaquinaVirtual;
import br.univali.compiladores.maquinavirtual.Out;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import br.univali.compiladores.maquinavirtual.Out;

/**
 *
 * @author Daniel
 */
public class MaquinaVirtualFrame extends javax.swing.JFrame {

	private MaquinaVirtual maquina;
    
    private boolean breakThis = false;
    
	private int start;
	String valor;
	final Map<Integer,InstrucaoMaquinaVirtual> args;
	
    
	/**
     * 
     * Creates new form MaquinaVirtualFrame
     */
    public MaquinaVirtualFrame(final Map<Integer,InstrucaoMaquinaVirtual> args) {
    	this.args = args;
    	start = 1;
        initComponents();
        this.setVisible(true);
        this.outputTextArea.setEditable(false);
        maquina = new MaquinaVirtual();
        maquina.in = new In() {
			
			@Override
			public String readString() {
				try {
					inputTextField.setVisible(true);
					sendButton.setEnabled(true);
					return valor;
				} finally {

					inputTextField.setVisible(false);
					sendButton.setEnabled(false);
				}
			}
			
		};
		maquina.out = new Out() {
			
			@Override
			public void println(Object object) {
				outputTextArea.append(object + "\n");
			}
			
			@Override
			public void print(Object object) {
				outputTextArea.append(object + "");				
			}
		};
		maquina.finish = new Finish() {
			
			@Override
			public void exit(int statusCode) {
				if(statusCode == 0){
					outputTextArea.append("\nPrograma terminado com sucesso!");
				} else {
					outputTextArea.append("\nOcorreu um erro na execução do programa!");
				}
				breakThis =true;
				inputTextField.setVisible(false);
				sendButton.setEnabled(false);
			}
		};
		this.executaInstrucoes(args);
        
    }

    
    public void executaInstrucoes(Map<Integer,InstrucaoMaquinaVirtual>  args){
    	try {
			for(int i = start; !breakThis && i < args.size(); i = maquina.PONTEIRO, start++){
				
				InstrucaoMaquinaVirtual instrucao = args.get(i);
				if(instrucao.getCodigo().equals(CodigoInstrucao.REA)&& this.valor == null){

					inputTextField.setVisible(true);
					sendButton.setEnabled(true);
					break;
				}
	    		try {
	    			maquina.getClass().getDeclaredMethod(instrucao.getCodigo().nome().toUpperCase(), instrucao.getParametro().getClass()).invoke(maquina, instrucao.getParametro());
	    		} catch (NoSuchMethodException e) {
	    			try {
	    				maquina.getClass().getDeclaredMethod(instrucao.getCodigo().nome().toUpperCase(), Object.class).invoke(maquina, instrucao.getParametro());
	    			} catch (NoSuchMethodException e2) {
		    			maquina.getClass().getDeclaredMethod(instrucao.getCodigo().nome().toUpperCase(), String.class).invoke(maquina, instrucao.getParametro().toString());
			    		
		    		} 
	    		}

				if(instrucao.getCodigo().equals(CodigoInstrucao.REA)){
					this.valor = null;
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
			outputTextArea.append("\n\nERROR: " + e.getMessage());
			maquina.finish.exit(1);
		}
    }
    
    
   
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        outputTextArea = new javax.swing.JTextArea();
        inputTextField = new javax.swing.JTextField();
        sendButton = new javax.swing.JButton();
        sendButton.setAction(new Action() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				valor = inputTextField.getText();
				executaInstrucoes(args);
			}
			
			@Override
			public void setEnabled(boolean b) {
				this.setEnabled(b);				
			}
			
			@Override
			public void removePropertyChangeListener(PropertyChangeListener listener) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void putValue(String key, Object value) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public boolean isEnabled() {
				// TODO Auto-generated method stub
				return true;
			}
			
			@Override
			public Object getValue(String key) {
				// TODO Auto-generated method stub
				return null;
			}
			
			@Override
			public void addPropertyChangeListener(PropertyChangeListener listener) {
				// TODO Auto-generated method stub
				
			}
		});

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        outputTextArea.setColumns(20);
        outputTextArea.setRows(5);
        jScrollPane1.setViewportView(outputTextArea);

        sendButton.setText("Enviar");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1)
            .addGroup(layout.createSequentialGroup()
                .addComponent(inputTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 304, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(sendButton, javax.swing.GroupLayout.DEFAULT_SIZE, 90, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 285, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(inputTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(sendButton)))
        );

        pack();
    }// </editor-fold>

    // Variables declaration - do not modify
    private javax.swing.JTextField inputTextField;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea outputTextArea;
    private javax.swing.JButton sendButton;
    // End of variables declaration
}
